/*####################################################################################
  CLASS : qDojo.dijix.FormFactory
  =============================
  - A Form factory
  - Create form from JSON data
  - Validate before form submit
  - Types - text; email; password; number; date; time; combo; numSpin; checkBox; radio; file
  	
  - TODO
  	- Check textbox validation with regular expression (quick and dirty method used currently).
  	- AJAX(ination) abandoned...... try this later....conflict with recursive calling
  - WATCH OUT:
  	1. if NAME of Radio is "type" then default option is not selected !!
  	2. (only in IE) if Radio option is not changed then formToQuery will not include Radio value 
  		cause: in IE need to explicitly set <INPUT type=radio> tag's checked to "true".
  		howto: after invoking " new dijit.form.RadioButton " wait for a while before setting checked = true to 
  			   make sure dojo.parser have enough time to replace the <INPUT> with RadioButton tamplet thus creating 
  			   the actual <INPUT> tag. Trying to set checked = true, without waiting will result in "id not defined"!!
  			   Current wait time is 600ms .... 
  	
  ####################################################################################*/
  
dojo.provide("qDojo.dijix.FormFactory");

dojo.require("dijit.layout.ContentPane");

dojo.require("dijit.form.Form");
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.form.NumberTextBox");
dojo.require("dijit.form.DateTextBox");
dojo.require("dijit.form.TimeTextBox");
dojo.require("dijit.form.ComboBox");
dojo.require("dijit.form.FilteringSelect");
dojo.require("dijit.form.NumberSpinner");
dojo.require("dijit.form.CheckBox"); 
dojo.require("dijit.form.Button"); 
dojo.require("qDojo.dijix.FileUploader"); 
dojo.require("qDojo.dijix.CssRounded"); 
dojo.require("qDojo.core.StringEx"); 

dojo.require("dojo.data.ItemFileWriteStore");


dojo.declare("qDojo.dijix.FormFactory", dijit.layout.ContentPane , {
		formStruct : [ 	{ name:"General" , 	type:"separator"   }, 
						{ name:"Id" 	 , 		type:"number" , value:2 , min:1 , max:9999 , places:0 , required:true},							   		
						{ name:"Id Again" 	 , 		type:"number" , value:2 , required:true},							   		
				   		{ name:"Description Eng" , 	type:"text"  , required:"true" , min:3 , max:20 }, 
				   		{ name:"Access Management" , 	type:"separator"   }, 
				   		{ name:"Description Thai" , 	type:"text"  , required:"true" , min:3 , max:20 ,lang:"utf8"}, 
				   		{ name:"Description Both" , 	type:"text"  , required:"true" , min:3 , max:20 ,lang:"both"}, 
				   		{ name:"Description @*&#" , 	type:"text"  , required:"true" , min:3 , max:20 ,lang:"@*&#"}, 
				   		{ name:"Password" , 	type:"password"  , required:"true" , min:3 , max:20 ,lang:"@*&#"}, 
				   		{ name:"Email " , 	type:"email"  , required:"true" }, 
				   		{ name:"Time Resource" , 	type:"separator"   }, 
				   		{ name:"Date" , 		type:"date"  , value:"10 1,2008" , required: true}, // MM dd, yyyy
						{ name:"Start Time" , 	type:"time"  , value:"2:12:12" , readOnly:true },  // HH:mm:ss
						{ name:"Stop Time" , 	type:"time"  , value:"17:12:12"  , required:true },
						{ name:"Details" , 	type:"separator"   }, 
						{ name:"Town" , 		type:"combo" , value:"Kathmandu" , options:[{name:"Kathmandu"},{name:"Biratnagar"},{name:"Gorkha"},{name:"Butwal"},{name:"Pokhara"}]},	
						{ name:"Count" , 		type:"numSpin"  , value:14 , min:12 , max:22 , smallDelta:2 , places:1 , required:true},
						{ name:"Clear before takeoff", type:"checkBox"  , value:"" },
						{ name:"Fav Band" ,		type:"radio" , options:["Metallica" , "Pink Floyd" , "Greenday" ] , checked: 2},
					//	{ name:"File Upload" , 	type:"separator"   }, 
						{ name:"Fax File" ,		type:"file"  , fileType:"tif" , required: true},
						{ name:"Voice File" ,	type:"file"  , fileType:""}									
				 	],		
		formStructText	: "null",		 	
		formId			: "formId" ,  // ids for normal form and file form derived from this
		method			: "POST" ,
		action 			: "howdy",
		hasFile			: false, 		
		submitLabel		: "Submit" , 
		cancelLabel		: "Cancel" ,
		clearLabel		: "Clear" ,		
		showCancel		: true,
		showClear		: false,		
		// -------------------------------- 	
		form: 		null ,	
		fileForm: 	null ,	 			 						
		lastValidation: false,
		// ======================================================================
		//	Post create widget 
		// ----------------------------------------------------------------------		
		postCreate: function() {		
			this.inherited(arguments);										
			
			if( this.formStructText != "null")
				this.formStruct = eval(this.formStructText);
			this.createForm();									
		},	
		// ======================================================================
		//	Construct Form 
		// ----------------------------------------------------------------------		 
		createForm: function(node){			
			
			var md = document.createElement("div");
			this.domNode.appendChild(md);			
			// create normal form
			this.form = new dijit.form.Form({id:this.formId+"Form", method:this.method , action:this.action });						
			md.appendChild(this.form.domNode);			
			
			// create file form
			this.fileForm = new dijit.form.Form( {id: this.formId+"File" , method: this.method } );
			this.fileForm.setAttribute( "enctype" , "multipart/form-data" );
			if(dojo.isIE) // some special attention to IE!!
				this.fileForm.setAttribute( "encoding" ,  "multipart/form-data");			
			md.appendChild(this.fileForm.domNode);			
			
			// create normal form table
			var table  = document.createElement("table");							
			table.border = 0;	table.cellSpacing = 5;	table.cellPadding = 5;	table.width = dojo.isFF>0? "100%" : "90%";												
			this.form.domNode.appendChild(table);
			
			var tbody  = document.createElement("tbody");							
			table.appendChild(tbody);							
			
			var fileTable  = document.createElement("table");							
			fileTable.border = 0;	fileTable.cellSpacing = 5;	fileTable.cellPadding = 5;	fileTable.width = dojo.isFF>0? "100%" : "90%";						
			this.fileForm.domNode.appendChild(fileTable);			
			
			var fileTbody  = document.createElement("tbody");										
			fileTable.appendChild( fileTbody );			
			
			// start populating the form
			var struct = this.formStruct;
			for(var i=0 ; i < struct.length ; i++  ){											
				var ele = struct[i];
				if( ele.type == "file"){	
					if(this.hasFile){
						var tr 	= document.createElement("tr");				
						var td1 = document.createElement("td");					
						var td2 = document.createElement("td");												
											
						td1.align = "right";	td1.width = "30%" ;	td1.innerHTML = ele.name + " :";
						
						this.addFormElement( ele , td2);												
						
						tr.appendChild(td1);
						tr.appendChild(td2);
						fileTbody.appendChild(tr);				
					}					
				}else if(ele.type == "separator"){
					var tr = document.createElement("tr");
					var td = document.createElement("td");			
					td.colSpan = "2";	
					this.addFormElement(ele , td);
					tr.appendChild(td);
					tbody.appendChild(tr);				
				}else{
					var tr 	= document.createElement("tr");				
					var td1 = document.createElement("td");				
					//td1.width = "Auto"; //<-- not working with IE!!
					td1.align = "right";	
					td1.innerHTML = (ele.type!="checkBox")? ele.name + " :" : "";
					var td2 = document.createElement("td");								
					this.addFormElement(ele , td2);										
					tr.appendChild(td1);
					tr.appendChild(td2);
					tbody.appendChild(tr);					
				}								
			}			
			// create a margin
			var tr = document.createElement("tr");
			var td = document.createElement("td");			
			td.colSpan = "2";
			var d  = document.createElement("div");			
			d.style.cssText = "border-top:1px solid #BEBEBE;background:#FFF;height:1px;font-size:0px";
			td.appendChild(d);
			tr.appendChild(td);			
			if(!this.hasFile)	tbody.appendChild(tr);				
			else				fileTbody.appendChild(tr);										
			// create submit and cancel buttons			
			tr 	= document.createElement("tr");
			td	= document.createElement("td");	
			td.colSpan = "2";
			tr.appendChild(td);												
						
			var saveBtt 	= new dijit.form.Button({label:this.submitLabel});
			var clearBtt 	= this.showClear?  new dijit.form.Button({label:this.clearLabel }) : null;						
			var cancelBtt 	= this.showCancel? new dijit.form.Button({label:this.cancelLabel}) : null;	
			
									td.appendChild(saveBtt.domNode);
			if(clearBtt != null)	td.appendChild(clearBtt.domNode);
			if(cancelBtt != null)	td.appendChild(cancelBtt.domNode);			
			
			if(!this.hasFile)	tbody.appendChild(tr);				
			else				fileTbody.appendChild(tr);				
			
			// make button connections	
				dojo.connect(saveBtt 	, "onClick" , this , "submitClicked");
			if(clearBtt != null)
				dojo.connect(clearBtt 	, "onClick" , this , "clearClicked");
			if(cancelBtt != null)	
				dojo.connect(cancelBtt 	, "onClick" , this , "cancelClicked");														
			//dojo.byId("callLogReportFormat_id_0").checked = true	
		},
		// ======================================================================
		//	Add a form element 
		// ----------------------------------------------------------------------		 		
		addFormElement: function(ele , node){			
			switch(ele.type){
				// -------------------------------------------------------------------------------------------
				// Only English - \\s\\w ; Only Thai - \\s\\W ; UTF8 and english - \\s\\w\\W 
				case "text": 
					var textbox = new dijit.form.ValidationTextBox({name:qDojo.core.toCamelCase( ele.name ), 
																	readOnly: (typeof ele.readOnly == "undefined")? "" : ele.readOnly , 
																	value: (typeof ele.value == "undefined")? "" : ele.value ,
																	required: (typeof ele.required == "undefined")? false : ele.required ,
																	regExp: (typeof ele.regExp == "undefined")? (( (typeof ele.min == "undefined")||(typeof ele.max == "undefined") )? ".*" : "^["+(typeof ele.lang == "undefined"? "\\s\\w" :(ele.lang == "utf8"? "\\s\\W" : ( ele.lang == "both"? "\\s\\W\\w" : "\\s\\w" ) ) )+"]{"+ele.min+","+ele.max+"}$") : ele.regExp
														});		
					node.appendChild(textbox.domNode);											
					break;							
				// -------------------------------------------------------------------------------------------								
				case "password": 
					var textbox = new dijit.form.ValidationTextBox({name:qDojo.core.toCamelCase( ele.name ), 
																	readOnly: (typeof ele.readOnly == "undefined")? "" : ele.readOnly , 
																	value: (typeof ele.value == "undefined")? "" : ele.value ,
																	required: (typeof ele.required == "undefined")? false : ele.required ,
																	regExp: ".*" ,
																	type: "password"
														});		
					node.appendChild(textbox.domNode);											
					break;							
				// -------------------------------------------------------------------------------------------								
				case "email": 
					var textbox = new dijit.form.ValidationTextBox({name:qDojo.core.toCamelCase( ele.name ), 
																	readOnly: (typeof ele.readOnly == "undefined")? "" : ele.readOnly , 
																	value: (typeof ele.value == "undefined")? "" : ele.value ,
																	required: (typeof ele.required == "undefined")? false : ele.required ,
																	regExp: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9]{2,6}$" 
														});							
					node.appendChild(textbox.domNode);											
					break;
				// -------------------------------------------------------------------------------------------								
				case "number": 
					var textbox = new dijit.form.NumberTextBox({	name:qDojo.core.toCamelCase( ele.name ), 
																	readOnly: (typeof ele.readOnly == "undefined")? "" : ele.readOnly , 
																	value: (typeof ele.value == "undefined")? "" : ele.value  ,
																	constraints:{min: (typeof ele.min == "undefined")? 1 : ele.min , max: (typeof ele.max == "undefined")? 99999999 : ele.max , places: (typeof ele.places == "undefined")? 0 : ele.places  },
																	required: (typeof ele.required == "undefined")? false : ele.required 
															});							
					node.appendChild(textbox.domNode);
					break;
				// -------------------------------------------------------------------------------------------						
				case "date": 
					var textbox = new dijit.form.DateTextBox({ 		name:qDojo.core.toCamelCase( ele.name ),
																	readOnly: (typeof ele.readOnly == "undefined")? "" : ele.readOnly ,
																	value: (typeof ele.value == "undefined")? "" : (ele.value == "now"? new Date() : new Date(ele.value)),
																	required: (typeof ele.required == "undefined")? false : ele.required 
															});							
					node.appendChild(textbox.domNode);	
					break;
				// -------------------------------------------------------------------------------------------						
				case "time": 
					var textbox = new dijit.form.TimeTextBox({		name:qDojo.core.toCamelCase( ele.name ),
																	readOnly: (typeof ele.readOnly == "undefined")? "" : ele.readOnly, 		
																	value: (typeof ele.value == "undefined")? "" : (ele.value == "now"? new Date() : new Date("1 1,1970 " + ele.value)),
																   	required: (typeof ele.required == "undefined")? false : ele.required 		
															});							
					node.appendChild(textbox.domNode);	
					break;
				// -------------------------------------------------------------------------------------------						
				case "combo": 
					var options = new dojo.data.ItemFileWriteStore({data: {identifier: 'name', items:ele.options }});						
					var textbox = new dijit.form.FilteringSelect({ 	store: options , 
																	name: qDojo.core.toCamelCase( ele.name ) , 
																	value: (typeof ele.value == "undefined")? "" : ele.value ,
																	width: "100px"
														});							
					node.appendChild(textbox.domNode);	
					break;	
				// -------------------------------------------------------------------------------------------												
				case "numSpin": 					
					var textbox = new dijit.form.NumberSpinner({ 	name: qDojo.core.toCamelCase( ele.name ) , 
																	value: (typeof ele.value == "undefined")? "" : ele.value ,
																	smallDelta: (typeof ele.smallDelta == "undefined")? 1 : ele.smallDelta ,
																	constraints:{min: (typeof ele.min == "undefined")? 1 : ele.min , max: (typeof ele.max == "undefined")? 99999999 : ele.max , places: (typeof ele.places == "undefined")? 0 : ele.places  },
																	required: (typeof ele.required == "undefined")? false : ele.required 
														});							
					node.appendChild(textbox.domNode);	
					break;		
				// -------------------------------------------------------------------------------------------												
				case "checkBox": 										
					var textbox = new dijit.form.CheckBox({ 		id: qDojo.core.toCamelCase( ele.name )+"_id" ,
																	readOnly: (typeof ele.readOnly == "undefined")? "" : ele.readOnly,		
																	name: qDojo.core.toCamelCase( ele.name ) , 
																	value: (typeof ele.value == "undefined")? "" : ele.value 
														});							
					node.appendChild(textbox.domNode);	
					var label = document.createElement("label");	label.innerHTML = ele.name;	label.setAttribute("for" , textbox.id);	node.appendChild(label);	
					break;
				// -------------------------------------------------------------------------------------------												
				case "radio":					 					
					for(var j=0 ; j<ele.options.length ; j++){						
						var id 		= qDojo.core.toCamelCase( ele.name )+"_id_"+j;
						var name 	= qDojo.core.toCamelCase( ele.name );
						var value 	= ele.options[j];												
						var chk 	= ((typeof ele.checked == "undefined") && (j==0))? true : (ele.checked == j? true : false);			
						var ip = document.createElement("input");
						ip.type = "radio";
						ip.checked = chk;
						node.appendChild(ip);
						var radio = new dijit.form.RadioButton({ id: id , name: name , value: value , checked: chk } , ip );								
						node.appendChild(radio.domNode);																		
						radio.startup();																
						// --- WATCHOUT : 2 (see top)			
						if(dojo.isIE & chk)	setTimeout("dojo.byId('"+id+"').checked = 1;" , 600);																		
						
						var label = document.createElement("label"); label.innerHTML = value+"&nbsp;";	label.htmlFor = id;	
						node.appendChild(label);																						
					}			
					
					break;									
				// -------------------------------------------------------------------------------------------													
				case "file":
					var widget = new qDojo.dijix.FileUploader({ 	fileType: (typeof ele.fileType == "undefined")? "*.*" : ele.fileType , 
																	required: (typeof ele.required == "undefined")? false : ele.required });
					node.appendChild(widget.domNode);										
					break;		
				// -------------------------------------------------------------------------------------------													
				case "separator":					
					var d  = document.createElement("div");d.style.cssText = "font-weight:bold;color:#527EB9";d.innerHTML = ele.name;node.appendChild(d);
					var d  = document.createElement("div");d.style.cssText = "border-top:1px solid #BEBEBE;background:#FFF;height:1px;font-size:0px";node.appendChild(d);
					break;			
			}
		},
		// ======================================================================
		//	Validate Form
		// ----------------------------------------------------------------------		 		
		validate: function(){		
			this.lastValidation = this.form.validate()? ( this.hasFile? ( this.fileForm.validate()? 2 : 0 ) : 1  ) : 0 ;			 		
			return this.lastValidation;
			
		},
		// ======================================================================
		//	Dispatch Form(s).Id is the widget whose AjaxHandler to use to send form data
		// ----------------------------------------------------------------------		 		
		dispatch: function(id){			
			if( this.validate() > 0){				
				if(this.lastValidation == 1)	
					dijit.byId(id).dispatchForm( this.action , this.form.id );				
				else if(this.lastValidation == 2)	
					dijit.byId(id).dispatchFormWithFile( this.action , this.form.id , this.fileForm.id );						
			}	
			return this.lastValidation;			
		},
		// ======================================================================
		//	On Save Button Clicked
		// ----------------------------------------------------------------------		 		
		submitClicked: function(){	
			
		},		
		// ======================================================================
		//	On Clear Button Clicked
		// ----------------------------------------------------------------------		 		
		clearClicked: function(){
			console.log("clear all input values");
			var ips = dojo.query("input", this.id);
			dojo.forEach(ips, function(ips){ ips.value = "";} ); 
			
		},
		// ======================================================================
		//	On Cancel Button Clicked
		// ----------------------------------------------------------------------		 		
		cancelClicked: function(){
			
		},
		clean: function(){
			this.destroyRecursive();
		},		 
		// ======================================================================
		//	Convert form values to query
		// ----------------------------------------------------------------------		 		
		formToQuery: function(){
			return dojo.formToQuery(this.form.id);
		},
		// ======================================================================
		//	Convert form values to object
		// ----------------------------------------------------------------------		 		
		formToObject: function(){
			return dojo.formToObject(this.form.id);
		}
});
